<template>
  <!--
    selectedKeys：当前选中菜单
    open-keys：当前展开的 SubMenu 菜单项 key 数组，可以通过 openChang 方法更改
  -->
  <a-menu
    mode="inline"
    theme="dark"
    :inline-collapsed="$store.state.layout.collapsed"
    :selected-keys="selectedKeys"
    :open-keys="openKeys"
    @openChange="handleOpenChange"
  >
    <template v-for="item in menus">
      <a-menu-item v-if="!item.children" :key="item.id" @click="handleMenuItemClick(item)">
        <a-icon :type="item.menuIcon"/>
        <span>{{ item.title }}</span>
      </a-menu-item>
      <sub-menu v-else :key="item.id" :menu-info="item"/>
    </template>
  </a-menu>
</template>

<script>
import SubMenu from './SubMenu';
import { map } from 'lodash-es';
import emitter from '@/utils/emitter';
import Events from '@/utils/event';

export default {
  name: 'SideMenu',
  components: { SubMenu },
  props: {
    menus: {
      type: Array,
      default: () => ([])
    }
  },
  data () {
    return {
      selectedKeys: [], // 被选中的菜单
      rootSubmenuKeys: [], // 所有 sub-menu 的第一级
      openKeys: [] // 当前展开的 SubMenu 菜单项 key 数组
    };
  },
  methods: {
    handleMenuItemClick (data) {
      emitter.emit(Events.ADD_TAB, data);
      this.$router.push('/' + data.path);
    },
    findParents (id, list = [], result = []) {
      for (let i = 0; i < list.length; i += 1) {
        const item = list[i];
        // 找到目标
        if (item.id === id) {
          // 找到了,加入到结果中
          result.push(item.id);
          // 因为可能在第一层就找到了结果，直接返回当前结果
          if (result.length === 1) {
            return result;
          }
          return true;
        }
        // 如果存在下级节点，则继续遍历
        if (item.children) {
          // 预设本次是需要的节点并加入到最终结果result中
          result.push(item.id);
          const find = this.findParents(id, item.children, result);
          // 如果不是false则表示找到了，直接return，结束递归
          if (find) {
            return result;
          }
          // 到这里，意味着本次并不是需要的节点，则在result中移除
          result.pop();
        }
      }
      // 如果都走到这儿了，也就是本轮遍历children没找到，将此次标记为false
      return false;
    },
    findCurrent (id, list = [], result = {}) {
      for (let i = 0; i < list.length; i++) {
        const item = list[i];
        if (item.id === id) {
          Object.assign(result, item);
        }
        if (item.children && item.children.length) {
          this.findCurrent(id, item.children, result);
        }
      }
      return result;
    },
    handleOpenChange (openKeys) {
      const latestOpenKey = openKeys.find(key => this.openKeys.indexOf(key) === -1);
      if (this.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
        this.openKeys = openKeys;
      } else {
        this.openKeys = latestOpenKey ? [latestOpenKey] : [];
      }
    }
  },
  created () {
    const id = this.$route.meta && this.$route.meta.id;
    this.selectedKeys = id ? [id] : [];
    this.rootSubmenuKeys = map(this.menus, item => item.id);
    this.openKeys = this.findParents(id, this.menus, []) || [];
    const currentMenu = this.findCurrent(id, this.menus, {});

    // SideMenu 和 TabMenu 是兄弟组件，为了保证 emitter.on 响应
    this.$nextTick(() => {
      if (currentMenu.id) {
        emitter.emit(Events.ADD_TAB, {
          id: currentMenu.id,
          title: currentMenu.title,
          path: currentMenu.path
        });
      }
    });
  },
  watch: {
    '$route.meta' (newVal) {
      if (newVal.id) {
        this.selectedKeys = [newVal.id];
        this.openKeys = this.findParents(newVal.id, this.menus, []);
      } else {
        this.selectedKeys = [];
        this.openKeys = [];
      }
    }
  }
};
</script>
